#include "threadpool.hpp"
#include <chrono>
#include <future>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <random>
#include <thread>
#include <vector>

class Benchmark {
public:
  struct Result {
    std::string test_name;
    double duration_ms;
    double throughput_ops_per_sec;
    size_t total_tasks;
  };

private:
  std::vector<Result> results;

  template <typename Func>
  Result time_execution(const std::string &name, size_t task_count,
                        Func &&func) {
    auto start = std::chrono::high_resolution_clock::now();
    func();
    auto end = std::chrono::high_resolution_clock::now();

    auto duration =
        std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    double duration_ms = duration.count() / 1000.0;
    double throughput = (task_count * 1000.0) / duration_ms;

    return {name, duration_ms, throughput, task_count};
  }

public:
  // 测试1: CPU密集型任务
  void test_cpu_intensive() {
    const size_t task_count = 10000;
    Thread::threadpool pool;

    auto result = time_execution("CPU Intensive Tasks", task_count, [&]() {
      std::vector<std::future<long long>> futures;
      futures.reserve(task_count);

      for (size_t i = 0; i < task_count; ++i) {
        futures.push_back(pool.submit([i]() -> long long {
          long long sum = 0;
          for (int j = 0; j < 1000; ++j) {
            sum += (i * j) % 997; // 一些计算
          }
          return sum;
        }));
      }

      for (auto &f : futures) {
        f.get();
      }
    });

    results.push_back(result);
  }

  // 测试2: I/O模拟任务
  void test_io_simulation() {
    const size_t task_count = 5000;
    Thread::threadpool pool;

    auto result = time_execution("I/O Simulation Tasks", task_count, [&]() {
      std::vector<std::future<int>> futures;
      futures.reserve(task_count);

      for (size_t i = 0; i < task_count; ++i) {
        futures.push_back(pool.submit([i]() -> int {
          // 模拟I/O延迟
          std::this_thread::sleep_for(
              std::chrono::microseconds(100 + (i % 50)));
          return static_cast<int>(i);
        }));
      }

      for (auto &f : futures) {
        f.get();
      }
    });

    results.push_back(result);
  }

  // 测试3: 混合优先级任务
  void test_priority_tasks() {
    const size_t task_count = 8000;
    Thread::threadpool pool;

    auto result = time_execution("Mixed Priority Tasks", task_count, [&]() {
      std::vector<std::future<int>> futures;
      futures.reserve(task_count);

      std::random_device rd;
      std::mt19937 gen(rd());
      std::uniform_int_distribution<> dis(0, 2);

      for (size_t i = 0; i < task_count; ++i) {
        Thread::TaskPriority priority;
        switch (dis(gen)) {
        case 0:
          priority = Thread::TaskPriority::HIGH;
          break;
        case 1:
          priority = Thread::TaskPriority::NORMAL;
          break;
        case 2:
          priority = Thread::TaskPriority::LOW;
          break;
        }

        futures.push_back(pool.submit(
            [i]() -> int {
              int sum = 0;
              for (int j = 0; j < 100; ++j) {
                sum += (i + j) % 100;
              }
              return sum;
            },
            priority));
      }

      for (auto &f : futures) {
        f.get();
      }
    });

    results.push_back(result);
  }

  // 测试4: 快速小任务
  void test_lightweight_tasks() {
    const size_t task_count = 100000;
    Thread::threadpool pool;

    auto result = time_execution("Lightweight Tasks", task_count, [&]() {
      std::vector<std::future<int>> futures;
      futures.reserve(task_count);

      for (size_t i = 0; i < task_count; ++i) {
        futures.push_back(
            pool.submit([i]() -> int { return static_cast<int>(i * 2 + 1); }));
      }

      for (auto &f : futures) {
        f.get();
      }
    });

    results.push_back(result);
  }

  // 测试5: 不同线程数的性能对比
  void test_thread_scaling() {
    const size_t task_count = 20000;
    std::vector<size_t> thread_counts = {
        1, 2, 4, 8, 16, std::thread::hardware_concurrency()};

    for (size_t thread_num : thread_counts) {
      Thread::threadpool pool(thread_num);

      std::string test_name =
          "Scaling Test (" + std::to_string(thread_num) + " threads)";
      auto result = time_execution(test_name, task_count, [&]() {
        std::vector<std::future<long long>> futures;
        futures.reserve(task_count);

        for (size_t i = 0; i < task_count; ++i) {
          futures.push_back(pool.submit([i]() -> long long {
            long long sum = 0;
            for (int j = 0; j < 500; ++j) {
              sum += (i * j) % 1009;
            }
            return sum;
          }));
        }

        for (auto &f : futures) {
          f.get();
        }
      });

      results.push_back(result);
    }
  }

  // 测试6: 批量提交vs逐个提交
  void test_batch_vs_individual() {
    const size_t task_count = 15000;

    // 逐个提交
    {
      Thread::threadpool pool;
      auto result = time_execution("Individual Submit", task_count, [&]() {
        std::vector<std::future<int>> futures;

        for (size_t i = 0; i < task_count; ++i) {
          futures.push_back(
              pool.submit([i]() -> int { return static_cast<int>(i % 1000); }));
        }

        for (auto &f : futures) {
          f.get();
        }
      });
      results.push_back(result);
    }

    // 批量提交
    {
      Thread::threadpool pool;
      auto result = time_execution("Batch Submit", task_count, [&]() {
        std::vector<std::future<int>> futures;
        futures.reserve(task_count);

        // 先提交所有任务
        for (size_t i = 0; i < task_count; ++i) {
          futures.push_back(
              pool.submit([i]() -> int { return static_cast<int>(i % 1000); }));
        }

        // 再获取所有结果
        for (auto &f : futures) {
          f.get();
        }
      });
      results.push_back(result);
    }
  }

  // 运行所有测试
  void run_all_tests() {
    std::cout << "=== ThreadPool Benchmark ===\n\n";
    std::cout << "Hardware concurrency: " << std::thread::hardware_concurrency()
              << " threads\n\n";

    std::cout << "Running CPU intensive test...\n";
    test_cpu_intensive();

    std::cout << "Running I/O simulation test...\n";
    test_io_simulation();

    std::cout << "Running priority tasks test...\n";
    test_priority_tasks();

    std::cout << "Running lightweight tasks test...\n";
    test_lightweight_tasks();

    std::cout << "Running thread scaling test...\n";
    test_thread_scaling();

    std::cout << "Running batch vs individual test...\n";
    test_batch_vs_individual();

    print_results();
  }

  // 打印结果
  void print_results() {
    std::cout << "\n=== Benchmark Results ===\n";
    std::cout << std::left << std::setw(35) << "Test Name" << std::setw(15)
              << "Duration (ms)" << std::setw(20) << "Throughput (ops/s)"
              << std::setw(12) << "Total Tasks" << "\n";
    std::cout << std::string(82, '-') << "\n";

    for (const auto &result : results) {
      std::cout << std::left << std::setw(35) << result.test_name
                << std::setw(15) << std::fixed << std::setprecision(2)
                << result.duration_ms << std::setw(20) << std::fixed
                << std::setprecision(0) << result.throughput_ops_per_sec
                << std::setw(12) << result.total_tasks << "\n";
    }

    // 计算总体统计
    double total_duration = 0;
    size_t total_tasks = 0;
    for (const auto &result : results) {
      total_duration += result.duration_ms;
      total_tasks += result.total_tasks;
    }

    std::cout << "\n=== Summary ===\n";
    std::cout << "Total tests: " << results.size() << "\n";
    std::cout << "Total tasks executed: " << total_tasks << "\n";
    std::cout << "Total execution time: " << std::fixed << std::setprecision(2)
              << total_duration << " ms\n";
    std::cout << "Average throughput: " << std::fixed << std::setprecision(0)
              << (total_tasks * 1000.0) / total_duration << " ops/s\n";
  }
};

int main() {
  try {
    Benchmark benchmark;
    benchmark.run_all_tests();
  } catch (const std::exception &e) {
    std::cerr << "Benchmark failed: " << e.what() << std::endl;
    return 1;
  }

  return 0;
}